/******************************************************************************
** 公司名称：天津柯迪斯科技有限公司
** 版权信息：
** 文件名称： App_Protocol_ANANDA_V11.c
** 模块名称： 安乃达V11协议处理模块
** 版 本 号： V1.0
** 作    者： 蒲磊
** 
** 修改记录： 版本     修改人      时间         修改内容
**            V1.0      蒲磊     2022.11.07     增加了协议V1.4.2支持，把V1.3.9和V1.4.2通过宏区分开
**            V1.1      蒲磊     2022.11.09     增加了设置模式接口的函数，修改了发送模式信息左移位数错误的Bug
                                                修改了限速设置时比例不对的Bug
                                                修改了轮径设置不对的Bug
                                                退出设置后，增加了发送模式的语句
**            V1.2      蒲磊     2022.11.17     修改了开机10秒以后，再清零写标志位。确保控制器能收到开机后的写限速和轮径（控制器上电时间比仪表晚） 
**            V1.3      蒲磊     2022.11.19     屏蔽了0x26欠压错误
**            V1.4      蒲磊     2022.12.27     获取系统时间戳函数统一改为ulBsp_Getticks()
**                                              日期校准函数，增加了参数传递
**            V1.5      蒲磊     2023.02.21     修改了写Trip寄存器时，数据长度应该为4，错写成2的Bug
**            V1.6      蒲磊     2023.03.27     修改了V1.42，获取轮径函数，返回值错误的Bug。错写成返回限速值
**            V1.7      蒲磊     2023.08.17     解析函数中，增加了对接收长度的判断。长度小于16，直接退出。防止通讯异常时，接收到单个数据，从而进CRC校验导致访问越界。
******************************************************************************/
 
/******************************************************************************
* 头文件
******************************************************************************/
#include <string.h>
#include "Config.h"
#include "App_Protocol.h"
#include "App_MainTask.h"
#include "App_Parameter.h"
/******************************************************************************
* 本文件宏定义 ('#define')                             
******************************************************************************/
#define FRAME_LEN_MAX		30		 /*最大帧长度*/
#define LOOP_CYCLE          25      /*Loop函数轮询周期，单位ms*/
/******************************************************************************
* 本文件类型定义 ('typedef')                                         
******************************************************************************/

/******************************************************************************
* 本文件静态函数声明 ('static')
******************************************************************************/
static void vPROTOCOL_Factory_Command(void);
static uint16_t CalcCRC16(uint8_t *pCh, uint16_t len);
static void vPROTOCOL_Factory_Response(uint8_t Cmd,uint16_t Response);
static void vPROTOCOL_Get_Data_ANANDA(void);
static void vPROTOCOL_Send_ANANDA(void);

/******************************************************************************
* 全局变量定义 
******************************************************************************/
uint8_t gucRx_Buffer[FRAME_LEN_MAX] = {0};
uint8_t gucTx_Buffer[FRAME_LEN_MAX] = {0};
uint8_t 					gucRx_Frame_OK 	= 0;
uint16_t 					gusRx_Len 		= 0;
stRECEIVED_DATA			gtReceived_Data 	= {0};
stSEND_DATA				gtSend_Data			= {0};
enSEND_DATA_TYPE		geSend_Data_Type 	= Send_Stop;
uint8_t					gucTimeOutError 	= 0;
uint32_t                gulCommunicationCnt = 0;
uint8_t                 gucReceivedConfigFrame = 0;/*是否已接收到配置帧标记*/
uint8_t                 gucReadRegEn[19] = {READ_TORQUE_EN,READ_CADENCE_EN,READ_TREADLEPOWER_EN,READ_MOTORPOWER_EN,READ_SPEED_EN,
                                            READ_AVGSPEED_EN,READ_MAXSPEED_EN,READ_TRIPTIME_EN,READ_TRIP_EN,READ_ODO_EN,
                                            READ_CONSUMPTION_EN,READ_TRIPCONSUMPTION_EN,READ_HARDWAREVER_EN,READ_SOFTWAREVER_EN,
                                            READ_SN_EN,READ_RANGE_EN,READ_HANDLE_LIMIT_EN,READ_SPEED_LIMIT_EN,READ_WHEELSIZE_EN};
uint8_t                 gucRegNum[19] = {0,2,4,6,8,10,12,14,16,20,24,26,28,40,52,68,70,72,74};
uint8_t                 gucRegLen[19] = {2,2,2,2,2,2,2,2,4,4,2,2,12,12,16,1,2,2,2};
uint8_t                 gucWriteRegEn[10];
static const uint16_t TBL_CRC16[256] =
{
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
};
/*****************************************************************************
* 函数实现 - global ('extern') and local ('static')
******************************************************************************/
 
 
/******************************************************************************
** 功  能：获取一帧协议数据
** 参  数：pData-指向数据的指针，Len-数据长度
** 返回值：无
** 备  注：该函数是协议处理模块对外获取数据的接口，接收到完整一帧后，调用该函数进行处理
******************************************************************************/
void vPROTOCOL_Get_OneFrame(uint8_t *pData,uint16_t Len)
{
	memcpy(gucRx_Buffer,pData,Len);		/*将数据拷贝到缓冲区*/
	gusRx_Len = Len;					/*数据长度*/
	gucRx_Frame_OK = 1;					/*接收到一帧标志置1*/
}

/******************************************************************************
** 功  能：解析协议数据
** 参  数：无
** 返回值：无
** 备  注：该函数在定时中断中被循环调用(25ms)。用于解析接收到的协议数据
******************************************************************************/
void vPROTOCOL_Loop(void)
{
	static uint16_t lusCnt = 0;
    
	if(gucRx_Frame_OK == 1)
	{
		gulCommunicationCnt = ulBsp_Getticks();
		gucTimeOutError = 0;
		if(gucRx_Buffer[0] == 0x3A && gucRx_Buffer[1] == 0x1C)
		{
			/*内部控制指令*/
			vPROTOCOL_Factory_Command();
		}
		else
		{
			/*调用不同的协议进行解析*/
            vPROTOCOL_Get_Data_ANANDA();

		}
		gucRx_Frame_OK = 0;
	}
	else
	{
		/*当发送状态为停止时，不报通讯超时错误*/
		if(geSend_Data_Type != Send_Stop)
		{
			/*通讯超时时间，10s*/
			if(ulBsp_Getticks() - gulCommunicationCnt > 10000)
			{
				gucTimeOutError = 1;
			}
		}
		else
		{
			gucTimeOutError = 0;
			gulCommunicationCnt = ulBsp_Getticks();
		}
	}
    /*100ms发送一次数据*/
    if(++lusCnt > 100 / LOOP_CYCLE)
    {
        vPROTOCOL_Send_ANANDA();
        lusCnt = 0;
    }

}

/******************************************************************************
** 功  能：设置大灯状态
** 参  数：State-大灯状态。0-关闭，1-打开
** 返回值：无
** 备  注：所有协议通用
******************************************************************************/
void vPROTOCOL_Set_Lamp(uint8_t State)
{
	gtSend_Data.Lamp = State == 0 ? 0 : 1;
}


/******************************************************************************
** 功  能：设置档位
** 参  数：Pas-档位值，最大为9，最小为-1,-1表示助推档
** 返回值：无
** 备  注：本函数不对档位值的合理性做检查。请保证传入的档位值正确。
**         所有协议通用
******************************************************************************/
void vPROTOCOL_Set_Pas(int8_t Pas)
{
    if(Pas > -1)
    {
        gtSend_Data.Walk = 0;
        gtSend_Data.Pas = Pas; 
    }
    else
    {
        gtSend_Data.Walk = 1;
    }
}
/******************************************************************************
** 功  能：设置转把限速值
** 参  数：Speed-限速值
** 返回值：无
** 备  注：本函数不对传入值的合理性做检查。请保证传入的值正确。
**         安乃达V11 1.4.2版本以上才支持设置转把限速
******************************************************************************/
void vPROTOCOL_Set_Handle_Limit(uint16_t Speed)
{
#if VER == V142
	gtSend_Data.Set_Handle_Limit = Speed;
    gucWriteRegEn[7] = 1;       /*置为对应的写入使能标记*/
#endif
}

/******************************************************************************
** 功  能：设置限速值
** 参  数：Speed-限速值，精度：0.1km/h
** 返回值：无
** 备  注：本函数不对传入值的合理性做检查。请保证传入的值正确。
**         安乃达V11 1.4.2版本以上才支持设置限速
******************************************************************************/
void vPROTOCOL_Set_Speed_Limit(uint16_t Speed)
{
#if VER == V142
	gtSend_Data.Set_Speed_Limit = Speed;
    gucWriteRegEn[8] = 1;
#endif
}

/******************************************************************************
** 功  能：设置轮径
** 参  数：Wheel-轮径值(实际轮径值的10倍，比如27.5寸，实际传入275)
** 返回值：无
** 备  注：本函数不对传入值的合理性做检查。请保证传入的值正确。
**         安乃达V11 1.4.2版本以上才支持设置轮径
******************************************************************************/
void vPROTOCOL_Set_Wheel(uint16_t Wheel)
{
#if VER == V142
    gtSend_Data.Set_WheelSize = Wheel;
    gucWriteRegEn[9] = 1;
#endif
}

/******************************************************************************
** 功  能：设置模式
** 参  数：Mode-模式
** 返回值：无
** 备  注：0-模式无效，1-模式1，2-模式2，3-模式3
******************************************************************************/
void vPROTOCOL_Set_Mode(uint8_t Mode)
{
    gtSend_Data.Mode = Mode;
}

/******************************************************************************
** 功  能：清Trip
** 参  数：无
** 返回值：无
** 备  注：       
******************************************************************************/
void vPROTOCOL_Set_ClearTrip(void)
{
    gtSend_Data.Set_AvgSpeed = 0;
    gtSend_Data.Set_MaxSpeed = 0;
    gtSend_Data.Set_Trip     = 0;
    gtSend_Data.Set_TripTime = 0;
    gucWriteRegEn[0] = 1;
    gucWriteRegEn[1] = 1;
    gucWriteRegEn[2] = 1;
    gucWriteRegEn[3] = 1;
}




/******************************************************************************
** 功  能：设置档位范围
** 参  数：Pas_Range-档位值范围，3，4，5，9
** 返回值：无
** 备  注：J协议不支持档位范围设置，为了兼容其他协议，该函数为空即可。
******************************************************************************/
void vPROTOCOL_Set_Pas_Range(int8_t Pas_Range)
{

}

/******************************************************************************
** 功  能：设置发送运行数据
** 参  数：无
** 返回值：无
** 备  注：本函数运行后，即开始发送运行数据。直到再次设置发送配置数据或停止
**         所有协议通用
******************************************************************************/
void vPROTOCOL_Send_Run_Data(void)
{
	geSend_Data_Type = Send_Run_Data;
}

/******************************************************************************
** 功  能：设置发送配置数据
** 参  数：无
** 返回值：无
** 备  注：本函数运行后，即开始发送配置数据。直到再次设置发送运行数据或停止
**         所有协议通用
******************************************************************************/
void vPROTOCOL_Send_Config_Data(void)
{
	geSend_Data_Type = Send_Config_Data;
}

/******************************************************************************
** 功  能：设置发送一次配置数据
** 参  数：无
** 返回值：无
** 备  注：本函数运行后，只发送一次配置数据。然后会转为发送运行数据
**         所有协议通用
******************************************************************************/
void vPROTOCOL_Send_Config_Data_OneTime(void)
{
	geSend_Data_Type = Send_Config_Data_OneTime;
    gucReceivedConfigFrame = 0;
}

/******************************************************************************
** 功  能：停止发送数据
** 参  数：无
** 返回值：无
** 备  注：本函数运行后，即停止发送数据。直到再次设置发送配置数据或发送运行数据
**         所有协议通用
******************************************************************************/
void vPROTOCOL_Send_Stop(void)
{
	geSend_Data_Type = Send_Stop;
}

/******************************************************************************
** 功  能：获取电量等级
** 参  数：无
** 返回值：电量等级。0-表示欠压，1-5表示电量等级
** 备  注：J协议用
******************************************************************************/
uint8_t ucPROTOCOL_Get_Volt_Level(void)
{
	return gtReceived_Data.Volt_Level;
}

/******************************************************************************
** 功  能：获取当前电流值
** 参  数：无
** 返回值：实际电流值的10倍。比如实际电流12.3A，返回123
** 备  注：所有协议通用
******************************************************************************/
uint16_t usPROTOCOL_Get_Current(void)
{
	if(gucTimeOutError == 1)
	{
		return 0;
	}
	else
	{
		return gtReceived_Data.Current;
	}
}

/******************************************************************************
** 功  能：获取电池容量
** 参  数：无
** 返回值：-1表示未获取到电池容量，电池容量，0-100%
** 备  注：安乃达协议不支持SOC，返回-1，为了兼容其他协议。
******************************************************************************/
int8_t cPROTOCOL_Get_Soc(void)
{
	return -1;
}



/******************************************************************************
** 功  能：获取当前车速
** 参  数：无
** 返回值：实际车速*10.比如返回120，实际车速即12.0Km/h
** 备  注：所有协议通用       
******************************************************************************/
uint16_t usPROTOCOL_Get_Speed(void)
{
#if 0 /*这是采用老的方式获取速度，安乃达V11协议也支持这种方式，但是可以更方便的读取寄存器来获取速度信息*/
    static uint16_t lusWheel_Diameter[] = {1277,1436,1596,1756,1915,2075,2140,2234};
    
	if(gtReceived_Data.Speed_Cnt >= 0x0DAC || gtReceived_Data.Speed_Cnt == 0 || gucTimeOutError == 1)
	{
		/*如果车轮转动一周的时间大于等于3500，或者等于0，或者通讯超时，即认为速度为0*/
		return 0;
	}
	else
	{
        /*根据周长计算转速，车速 = 周长(mm) * 36 / 车轮转一周的时间(ms) / 100*/
        return lusWheel_Diameter[gtSend_Data.Wheel_Index] * 36 / gtReceived_Data.Speed_Cnt / 100;	
	}
#else
    return gtReceived_Data.Speed;
#endif
}

/******************************************************************************
** 功  能：获取最大速度
** 参  数：无
** 返回值：最大速度，0.1km/h
** 备  注：
******************************************************************************/
uint16_t usPROTOCOL_Get_Speed_Max(void)
{
	return gtReceived_Data.MaxSpeed;
}

/******************************************************************************
** 功  能：获取平均速度
** 参  数：无
** 返回值：平均速度，0.1km/h
** 备  注：
******************************************************************************/
uint16_t usPROTOCOL_Get_Speed_Avg(void)
{
	return gtReceived_Data.AvgSpeed;
}

/******************************************************************************
** 功  能：获取电机功率
** 参  数：无
** 返回值：电机功率，W
** 备  注：
******************************************************************************/
uint16_t usPROTOCOL_Get_MotorPower(void)
{
	return gtReceived_Data.MotorPower;
}

/******************************************************************************
** 功  能：获取Trip
** 参  数：无
** 返回值：Trip,0.1Km
** 备  注：
******************************************************************************/
uint32_t ulPROTOCOL_Get_Trip(void)
{
	return gtReceived_Data.Trip;
}

/******************************************************************************
** 功  能：获取ODO
** 参  数：无
** 返回值：ODO,0.1Km
** 备  注：
******************************************************************************/
uint32_t ulPROTOCOL_Get_ODO(void)
{
	return gtReceived_Data.ODO;
}

/******************************************************************************
** 功  能：获取单次骑行时间
** 参  数：无
** 返回值：单次骑行时间，10S
** 备  注：
******************************************************************************/
uint16_t usPROTOCOL_Get_TripTime(void)
{
	return gtReceived_Data.TripTime;
}

/******************************************************************************
** 功  能：获取剩余里程
** 参  数：无
** 返回值：剩余里程，1km
** 备  注：
******************************************************************************/
uint8_t usPROTOCOL_Get_Range(void)
{
	return gtReceived_Data.Range;
}

/******************************************************************************
** 功  能：获取转把限速值
** 参  数：无
** 返回值：转把限速值，0.1km/h
** 备  注：
******************************************************************************/
uint16_t usPROTOCOL_Get_Handle_Limit(void)
{
#if VER == V142
	return gtReceived_Data.Handle_Speed_Limit;
#elif VER == V139
    return 0;
#endif
}

/******************************************************************************
** 功  能：获取助力限速值
** 参  数：无
** 返回值：助力限速值，0.1km/h
** 备  注：
******************************************************************************/
uint16_t usPROTOCOL_Get_Speed_Limit(void)
{
#if VER == V142
	return gtReceived_Data.Speed_Limit;
#elif VER == V139
    return 0;
#endif
}

/******************************************************************************
** 功  能：获取轮径值
** 参  数：无
** 返回值：轮径值，0.1Inch
** 备  注：
******************************************************************************/
uint16_t usPROTOCOL_Get_WheelSize(void)
{
#if VER == V142
	return gtReceived_Data.WheelSize;
#elif VER == V139
    uint16_t WheelTab[] = {0,80,100,120,140,160,180,200,220,240,260,270,275,280,290};
    if(gtReceived_Data.WheelSize_Index > 14)
    {
        return 290;
    }
    else
    {
        return WheelTab[gtReceived_Data.WheelSize_Index];
    }
#endif
}


/******************************************************************************
** 功  能：获取错误代码
** 参  数：无
** 返回值：十六进制的错误代码
** 备  注：包括30错误代码（通信超时）
**         所有协议通用
******************************************************************************/
uint8_t ucPROTOCOL_Get_Errcode(void)
{
	if(gucTimeOutError == 1)
	{
		return 0x30;
	}
	else
	{
		return gtReceived_Data.ErrCode;
	}
}

/******************************************************************************
** 功  能：工厂指令的应答
** 参  数：Cmd-要应答的指令，Response-要应答的参数
** 返回值：无
** 备  注：
******************************************************************************/
static void vPROTOCOL_Factory_Response(uint8_t Cmd,uint16_t Response)
{
    uint8_t lucRxBuffer[8];
    
    
    lucRxBuffer[0] = 0x3A;  /*0x3A,0x50是应答帧的帧头*/
    lucRxBuffer[1] = 0x50;
    lucRxBuffer[2] = Cmd;
    lucRxBuffer[3] = Response & 0x00FF;
    lucRxBuffer[4] = (Response >> 8) & 0x00FF;
    lucRxBuffer[5] = lucRxBuffer[2] + lucRxBuffer[3] + lucRxBuffer[4]; /*8位的和校验*/
    lucRxBuffer[6] = 0x0D;
    lucRxBuffer[7] = 0x0A;  /*0x0D,0x0A是固定帧尾*/
    
    USART_MCU_Send_Frame(lucRxBuffer,8);
    
}

/******************************************************************************
** 功  能：工厂指令的解析
** 参  数：无
** 返回值：无
** 备  注：
******************************************************************************/
void vPROTOCOL_Factory_Command(void)
{
	uint16_t n;
	uint16_t lusCheckSum = 0;
    uint16_t lusResponse;
	for(n = 0;n < gusRx_Len - 5;n++)
	{
		lusCheckSum += gucRx_Buffer[1 + n];		/*计算校验值，和校验*/
	}
	if((gucRx_Buffer[3] == gusRx_Len - 8) && (lusCheckSum == gucRx_Buffer[gucRx_Buffer[3] + 5] * 256UL + gucRx_Buffer[gucRx_Buffer[3] + 4]))
	{
		switch(gucRx_Buffer[2])
		{
			case 0x5D:		/*电压校准*/
			{
				lusResponse = vVoltage_Calibration();
                vPROTOCOL_Factory_Response(0x5D,lusResponse);
				break;
			}
			case 0x8E:		/*清除ODO*/
			{
				vClear_ODO();
                vPROTOCOL_Factory_Response(0x8E,5678); /*5678是针对清ODO的固定响应*/
				break;
			}
			case 0x6E:		/*校准光感*/
			{
				lusResponse = vPhotoDiode_Calibration();
                vPROTOCOL_Factory_Response(0x6E,lusResponse); 
				break;
			}
			case 0x71:		/*自动校准时间*/
			{
				vDateTime_Calibration(gucRx_Buffer[7],gucRx_Buffer[8],gucRx_Buffer[9],gucRx_Buffer[4],gucRx_Buffer[5],gucRx_Buffer[6]);
                vPROTOCOL_Factory_Response(0x71,1234); /*1234是针对校准时间的固定响应*/
				break;
			}
			default:break;
		}
	}
}


/******************************************************************************
** 功  能：解析安乃达V11协议数据
** 参  数：无
** 返回值：无
** 备  注：
******************************************************************************/
static void vPROTOCOL_Get_Data_ANANDA(void)
{
	uint16_t lusCheckSum = 0;
	uint8_t n;
    
	if(gusRx_Len < 16)
	{
		return;
	}
	
    lusCheckSum = CalcCRC16(gucRx_Buffer,gusRx_Len - 2);/*对除去最后2个字节外的所有数据做CRC16的校验*/

	/*起始是0x3A，0x1A，并且校验正确，认为接收数据无误*/
	if((gucRx_Buffer[0] == 0x3A) && (gucRx_Buffer[1] == 0x1A) && (gucRx_Buffer[gusRx_Len - 2] == lusCheckSum / 256) && (gucRx_Buffer[gusRx_Len - 1] == lusCheckSum % 256))
	{
        gtReceived_Data.WheelSize_Index = (gucRx_Buffer[4] >> 4) & 0x0F;    /*轮径值索引，一般用于V1.4.2版本之前的版本读取轮径*/
        gtReceived_Data.Volt_Level	= gucRx_Buffer[4] & 0x0F;			/*电量值，0表示欠压，1-5为电量*/
        gtReceived_Data.Current		= gucRx_Buffer[5] * 4;			    /*实际电流值 = 接收到的值*4*/
        gtReceived_Data.Speed_Cnt	= (uint16_t)gucRx_Buffer[6] << 8 | gucRx_Buffer[7];		/*车轮转动一周的脉冲时间*/
        if(gucRx_Buffer[8] >= 0x21 && (gucRx_Buffer[8] != 0x26) && gucRx_Buffer[8] <= 0x28 ) /*只显示21-28 除了27*/
        {
            gtReceived_Data.ErrCode	= gucRx_Buffer[8];					/*错误代码，屏蔽0x26欠压错误*/
        }
        else
        {
            gtReceived_Data.ErrCode = 0x00;			/*错误代码如果是其它值，都认为是无错误*/
        } 
        
        /*解析0x0D,0x0A后面的数据*/
        if(gucRx_Buffer[13] == 0x03)/*0x03表示读取某个寄存器地址的返回数据*/
        {
            switch(gucRx_Buffer[14])/*根据寄存器地址判断数据类型*/
            {
                case 0:/*实际脚踏力矩*/
                {    
                    gtReceived_Data.Torque = (uint16_t)gucRx_Buffer[17] << 8 | gucRx_Buffer[16];
                    break;
                }
                case 2:/*踏频*/
                {    
                    gtReceived_Data.Cadence = (uint16_t)gucRx_Buffer[17] << 8 | gucRx_Buffer[16];
                    break;
                }
                case 4:/*脚踏功率*/
                {    
                    gtReceived_Data.TreadlePower = (uint16_t)gucRx_Buffer[17] << 8 | gucRx_Buffer[16];
                    break;
                }
                case 6:/*电机功率*/
                {    
                    gtReceived_Data.MotorPower = (uint16_t)gucRx_Buffer[17] << 8 | gucRx_Buffer[16];
                    break;
                }
                case 8:/*当前速度*/
                { 
                    gtReceived_Data.Speed = (uint16_t)gucRx_Buffer[17] << 8 | gucRx_Buffer[16];
                    break;
                }
                case 10:/*平均速度*/
                {    
                    gtReceived_Data.AvgSpeed = (uint16_t)gucRx_Buffer[17] << 8 | gucRx_Buffer[16];
                    break;
                }
                case 12:/*最大速度*/
                {    
                    gtReceived_Data.MaxSpeed = (uint16_t)gucRx_Buffer[17] << 8 | gucRx_Buffer[16];
                    break;
                }
                case 14:/*单次骑行时间*/
                {    
                    gtReceived_Data.TripTime = (uint16_t)gucRx_Buffer[17] << 8 | gucRx_Buffer[16];
                    break;
                }
                case 16:/*单次里程*/
                {    
                    gtReceived_Data.Trip = (uint16_t)gucRx_Buffer[19] << 24 | (uint16_t)gucRx_Buffer[18] << 16 | (uint16_t)gucRx_Buffer[17] << 8 | gucRx_Buffer[16];
                    break;
                }
                case 20:/*总里程*/
                {   
                    gtReceived_Data.ODO = (uint16_t)gucRx_Buffer[19] << 24 | (uint16_t)gucRx_Buffer[18] << 16 | (uint16_t)gucRx_Buffer[17] << 8 | gucRx_Buffer[16];
                    break;
                }
                case 24:/*瞬时功耗*/
                {   
                    gtReceived_Data.Consumption = (uint16_t)gucRx_Buffer[17] << 8 | gucRx_Buffer[16];
                    break;
                }
                case 26:/*平均功耗*/
                {    
                    gtReceived_Data.TripConsumption = (uint16_t)gucRx_Buffer[17] << 8 | gucRx_Buffer[16];
                    break;
                }
                case 28:/*硬件版本*/
                {   
                    for(n = 0;n < 12;n++)
                    {
                        gtReceived_Data.HardwareVer[n] = gucRx_Buffer[16 + n];
                    }
                    break;
                }
                case 40:/*软件版本*/
                {    
                    for(n = 0;n < 12;n++)
                    {
                        gtReceived_Data.SoftwareVer[n] = gucRx_Buffer[16 + n];
                    }
                    break;
                }
                case 52:/*SN号*/
                {   
                    for(n = 0;n < 16;n++)
                    {
                        gtReceived_Data.SN[n] = gucRx_Buffer[16 + n];
                    }
                    break;
                }
                case 68:/*剩余里程*/
                {    
                    gtReceived_Data.Range = gucRx_Buffer[16];
                    break;
                }
                case 70:/*转把限速值*/
                {
                    gtReceived_Data.Handle_Speed_Limit = (uint16_t)gucRx_Buffer[17] << 8 | gucRx_Buffer[16];
                    break;
                }
                case 72:/*助力限速值*/
                {
                    gtReceived_Data.Speed_Limit = (uint16_t)gucRx_Buffer[17] << 8 | gucRx_Buffer[16];
                    break;
                }
                case 74:/*轮径值*/
                {
                    gtReceived_Data.WheelSize = (uint16_t)gucRx_Buffer[17] << 8 | gucRx_Buffer[16];
                    break;
                }
            }
        }
	}
	
	return;
}

/******************************************************************************
** 功  能：发送安乃达V11协议数据
** 参  数：无
** 返回值：无
** 备  注：该函数100ms调用一次
******************************************************************************/
static void vPROTOCOL_Send_ANANDA(void)
{
	//uint8_t lucWheel_Index;

	uint16_t lusChecksum = 0;
    static uint8_t lucWriteRegIndex = 0;/*写寄存器索引*/
    static uint8_t lucReadRegIndex = 0;/*读寄存器索引*/
    uint8_t n;
	uint8_t  lucFrameLen;

    gucTx_Buffer[0] = 0x3A;     /*帧头*/
    gucTx_Buffer[1] = 0x1A;     /*从机地址*/ 
    if(geSend_Data_Type == Send_Run_Data)
    {
        gucTx_Buffer[2] = 'F';		/*正常工作数据，帧头标志是F*/
    }
    else if(geSend_Data_Type == Send_Config_Data)
    {
        gucTx_Buffer[2] = 'S';		/*设置状态，帧头标志是S*/
    }
    gucTx_Buffer[3] = 0x02;     /*数据长度，固定为2（注意：安乃达V11协议，1.3.11版本，增加了2个字节，此处改为了4*/
    
    /*bit7:大灯状态，bit6-bit5:模式，bit4：助推功能,bit3-bit0：挡位*/
    gucTx_Buffer[4] = (gtSend_Data.Lamp << 7) | ((gtSend_Data.Mode & 0x03) << 5) | (gtSend_Data.Walk << 4) | (gtSend_Data.Pas);    
    
    gucTx_Buffer[5] = 0;    /*该字节在V11版本的协议中不起作用*/
    
    /*计算校验值，从gucTx_Buffer[1]开始计算*/
    for(n = 1;n < 6;n++)
    {
        lusChecksum += gucTx_Buffer[n];
    }
    
    /*填充校验值以及帧尾*/
    gucTx_Buffer[6] = lusChecksum % 256;
    gucTx_Buffer[7] = lusChecksum / 256;
    gucTx_Buffer[8] = 0x0D;
    gucTx_Buffer[9] = 0x0A;

    /*查询是否有要写的寄存器*/
    while((gucWriteRegEn[lucWriteRegIndex] == 0) && lucWriteRegIndex < 10)
    {
        lucWriteRegIndex++;
    }
    if(lucWriteRegIndex < 10)
    {
        switch(lucWriteRegIndex)
        {
            case 0:/*写平均速度*/
            {
                gucTx_Buffer[10] = 0x10;/*0x10是写寄存器指令*/
                gucTx_Buffer[11] = 0x00;/*寄存器地址*/
                gucTx_Buffer[12] = 0x02;/*数据长度*/
                gucTx_Buffer[13] = gtSend_Data.Set_AvgSpeed;/*要写入的数据低字节*/
                gucTx_Buffer[14] = gtSend_Data.Set_AvgSpeed >> 8;/*要写入的数据高字节*/
                break;
            }
            case 1:/*写最大速度*/
            {
                gucTx_Buffer[10] = 0x10;/*0x10是写寄存器指令*/
                gucTx_Buffer[11] = 2;/*寄存器地址*/
                gucTx_Buffer[12] = 2;/*数据长度*/
                gucTx_Buffer[13] = gtSend_Data.Set_MaxSpeed;/*要写入的数据低字节*/
                gucTx_Buffer[14] = gtSend_Data.Set_MaxSpeed >> 8;/*要写入的数据高字节*/
                break;
            }
            case 2:/*写单次骑行时间*/
            {
                gucTx_Buffer[10] = 0x10;/*0x10是写寄存器指令*/
                gucTx_Buffer[11] = 4;/*寄存器地址*/
                gucTx_Buffer[12] = 2;/*数据长度*/
                gucTx_Buffer[13] = gtSend_Data.Set_TripTime;/*要写入的数据低字节*/
                gucTx_Buffer[14] = gtSend_Data.Set_TripTime >> 8;/*要写入的数据高字节*/
                break;
            }
            case 3:/*写单次里程*/
            {
                gucTx_Buffer[10] = 0x10;/*0x10是写寄存器指令*/
                gucTx_Buffer[11] = 6;/*寄存器地址*/
                gucTx_Buffer[12] = 4;/*数据长度*/
                gucTx_Buffer[13] = gtSend_Data.Set_Trip;/*要写入的数据低字节*/
                gucTx_Buffer[14] = gtSend_Data.Set_Trip >> 8;/*要写入的数据高字节*/
                gucTx_Buffer[15] = gtSend_Data.Set_Trip >> 16;
                gucTx_Buffer[16] = gtSend_Data.Set_Trip >> 24;
                break;
            }
            case 4:/*复位故障*/
            {
                gucTx_Buffer[10] = 0x10;/*0x10是写寄存器指令*/
                gucTx_Buffer[11] = 14;/*寄存器地址*/
                gucTx_Buffer[12] = 1;/*数据长度*/
                gucTx_Buffer[13] = 0;/*要写入的数据*/
                break;
            }
            case 5:/*写SOC*/
            {
                gucTx_Buffer[10] = 0x10;/*0x10是写寄存器指令*/
                gucTx_Buffer[11] = 15;/*寄存器地址*/
                gucTx_Buffer[12] = 0x02;/*数据长度*/
                gucTx_Buffer[13] = gtSend_Data.Set_SOC;/*要写入的数据*/
                break;
            }
            case 6:/*写平均功耗*/
            {
                gucTx_Buffer[10] = 0x10;/*0x10是写寄存器指令*/
                gucTx_Buffer[11] = 16;/*寄存器地址*/
                gucTx_Buffer[12] = 2;/*数据长度*/
                gucTx_Buffer[13] = gtSend_Data.Set_TripConsumption;/*要写入的数据低字节*/
                gucTx_Buffer[14] = gtSend_Data.Set_TripConsumption >> 8;/*要写入的数据高字节*/
                break;
            }
            case 7:/*写转把限速值*/
            {
                gucTx_Buffer[10] = 0x10;/*0x10是写寄存器指令*/
                gucTx_Buffer[11] = 18;/*寄存器地址*/
                gucTx_Buffer[12] = 2;/*数据长度*/
                gucTx_Buffer[13] = gtSend_Data.Set_Handle_Limit;/*要写入的数据低字节*/
                gucTx_Buffer[14] = gtSend_Data.Set_Handle_Limit >> 8;/*要写入的数据高字节*/
                break;
            }
            case 8:/*写助力限速值*/
            {
                gucTx_Buffer[10] = 0x10;/*0x10是写寄存器指令*/
                gucTx_Buffer[11] = 20;/*寄存器地址*/
                gucTx_Buffer[12] = 2;/*数据长度*/
                gucTx_Buffer[13] = gtSend_Data.Set_Speed_Limit;/*要写入的数据低字节*/
                gucTx_Buffer[14] = gtSend_Data.Set_Speed_Limit >> 8;/*要写入的数据高字节*/
                break;
            }
            case 9:/*写轮径值*/
            {
                gucTx_Buffer[10] = 0x10;/*0x10是写寄存器指令*/
                gucTx_Buffer[11] = 22;/*寄存器地址*/
                gucTx_Buffer[12] = 2;/*数据长度*/
                gucTx_Buffer[13] = gtSend_Data.Set_WheelSize;/*要写入的数据低字节*/
                gucTx_Buffer[14] = gtSend_Data.Set_WheelSize >> 8;/*要写入的数据高字节*/
                break;
            }
        }
        /*开机5秒以后，再清零写标志，这样在开机后的5秒内，会一直写限速和轮径，确保控制器能收到（控制器上电时间比仪表要晚）*/
        if(ulBsp_Getticks() > 10000)
        {
            gucWriteRegEn[lucWriteRegIndex] = 0;/*清零对应的写入允许标志*/
        }
        if(lucWriteRegIndex < 10)
        {
            lucWriteRegIndex++;
        }
        else
        {
            lucWriteRegIndex = 0;
        }
        lucFrameLen = 13 + gucTx_Buffer[12];/*不带CRC16校验，总的帧长度*/
    }
    else
    {
        lucWriteRegIndex = 0;/*没有要写的寄存器，从0开始下一圈查询*/
        /*处理读寄存器请求,必须保证至少要有一个读寄存器请求*/
        while(gucReadRegEn[lucReadRegIndex] == 0)
        {
            if(lucReadRegIndex < 19)
            {
                lucReadRegIndex++;
            }
            else
            {
                lucReadRegIndex = 0;
            }
        }

        gucTx_Buffer[10] = 0x03;/*读寄存器命令*/
        gucTx_Buffer[11] = gucRegNum[lucReadRegIndex];/*寄存器地址*/
        gucTx_Buffer[12] = gucRegLen[lucReadRegIndex];/*数据长度*/
        if(lucReadRegIndex < 19)
        {
            lucReadRegIndex++;
        }
        else
        {
            lucReadRegIndex = 0;
        }
        
        lucFrameLen = 13;/*不带CRC16校验，总的帧长度*/
        
    }
    
    /*CRC16校验*/
    lusChecksum = CalcCRC16(gucTx_Buffer,lucFrameLen);
    gucTx_Buffer[lucFrameLen] = lusChecksum >> 8;
    gucTx_Buffer[lucFrameLen + 1] = lusChecksum;
    
    USART_MCU_Send_Frame(gucTx_Buffer,lucFrameLen + 2);		/*发送数据*/
    
}


/******************************************************************************
** 功  能：复位通信超时计数变量
** 参  数：无
** 返回值：无
** 备  注：
******************************************************************************/
void vPROTOCOL_ResetCommunicationOverTime(void)
{
    __disable_irq();
    gucTimeOutError = 0;
    gulCommunicationCnt = ulBsp_Getticks();
    __enable_irq();
    
}


/******************************************************************************
** 功  能：开机上电时，设置默认要发送给控制器的数据
** 参  数：无
** 返回值：无
** 备  注：
******************************************************************************/
void vPROTOCOL_Set_Value_When_PowerOn(void)
{ 
    vPROTOCOL_Set_Wheel(usGet_Wheel_Size(gtParam.Wheel_Diameter));  /*轮径，为和其他协议兼容，轮径是×10以后的值*/
    vPROTOCOL_Set_Pas(0);                                           /*开机LOGO界面发0档*/
    vPROTOCOL_Set_Speed_Limit(gtParam.Speed_Limit * 10);            /*限速*/
    vPROTOCOL_Set_Mode(gtParam.Mode);                               /*模式*/
    
    vPROTOCOL_Send_Run_Data();                                      /*开机时运行数据*/
}

/******************************************************************************
** 功  能：退出设置时，设置默认要发送给控制器的数据
** 参  数：无
** 返回值：无
** 备  注：
******************************************************************************/
void vPROTOCOL_Set_Value_When_ExitSetting(void)
{
    vPROTOCOL_Set_Wheel(usGet_Wheel_Size(gtParam.Wheel_Diameter));  /*轮径，为和其他协议兼容，轮径是×10以后的值*/
    vPROTOCOL_Set_Speed_Limit(gtParam.Speed_Limit * 10);            /*限速*/
    vPROTOCOL_Set_Mode(gtParam.Mode);                               /*模式*/
    vPROTOCOL_Send_Run_Data();                                      /*退出设置后，发送运行数据*/
}

/******************************************************************************
** 功  能：CRC16计算程序
** 参  数：pCh-数据指针，len-数据长度
** 返回值：CRC16校验值
** 备  注：
******************************************************************************/
static uint16_t CalcCRC16(uint8_t *pCh, uint16_t len)
{
    uint16_t crcVal = 0;
    uint8_t da = 0;
    crcVal = 0;
    
    while (len-- != 0)
    {
        da = (uint8_t)(crcVal >> 8);
        crcVal <<= 8;
        crcVal ^= TBL_CRC16[da ^ *pCh];
        pCh++;
    }
    
    return (crcVal);
}

